package com.hangzhou.xyj.manager;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.hangzhou.xyj.XYJApplication;
import com.hangzhou.xyj.db.GroupPushMsgDao;
import com.hangzhou.xyj.db.SimpleUserDao;
import com.hangzhou.xyj.event.HXConnectedEvent;
import com.hangzhou.xyj.event.NewMessageEvent;
import com.hangzhou.xyj.model.GroupPushMsgModel;
import com.hangzhou.xyj.model.SimpleUserModel;
import com.hangzhou.xyj.model.UserModel;
import com.hangzhou.xyj.model.type.EGroupPushType;
import com.hangzhou.xyj.model.type.EMessageType;
import com.hangzhou.xyj.net.handler.GetUsersInfoHandler;
import com.hangzhou.xyj.net.http.HttpLoader;
import com.hangzhou.xyj.net.listener.HttpResponseListener;
import com.hangzhou.xyj.net.request.GetUsersInfoReq;
import com.hangzhou.xyj.ui.dialog.TipsDialog;
import com.hangzhou.xyj.utils.EventBusUtil;
import com.hangzhou.xyj.utils.LogUtil;
import com.hangzhou.xyj.utils.StringUtil;
import com.hyphenate.EMCallBack;
import com.hyphenate.EMConnectionListener;
import com.hyphenate.EMError;
import com.hyphenate.EMMessageListener;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMConversation;
import com.hyphenate.chat.EMMessage;
import com.hyphenate.chat.EMMessageBody;
import com.hyphenate.chat.EMOptions;
import com.hyphenate.easeui.controller.EaseUI;
import com.hyphenate.easeui.domain.EaseUser;
import com.hyphenate.exceptions.HyphenateException;
import com.hyphenate.util.NetUtils;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : neo.duan
 * @date : 	 2016/3/26
 * @desc : 聊天管理器：登录，注销
 */
public class ChatManager {
    private static final String TAG = "ChatManager";
    private EaseUI easeUI;
    private Context mContext;

    private ChatManager() {
    }

    public static final ChatManager getInstance() {
        return ChatManagerHolder.instance;
    }

    public void init(Context context) {
        mContext = context;
        EMOptions options = new EMOptions();
        // 默认添加好友时，是不需要验证的，改成需要验证
        options.setAcceptInvitationAlways(true);
//        options.setAutoAcceptGroupInvitation(false);
        //初始化
//        EMClient.getInstance().init(context, options);
        //在做打包混淆时，关闭debug模式，避免消耗不必要的资源
        easeUI = EaseUI.getInstance();
        easeUI.init(context, options);
        setEaseUIProviders();

        EMClient.getInstance().setDebugMode(true);
        //新消息接受监听器
        EMClient.getInstance().chatManager().addMessageListener(new NewEMMessageListener());
        //注册一个监听连接状态的listener
        EMClient.getInstance().addConnectionListener(new MyConnectionListener());

        //增加加群组信息
//        EMClient.getInstance().groupManager().addGroupChangeListener();

        //注册EventBus
        EventBusUtil.register(this);
    }

    /**
     * 登录聊天服务器
     *
     * @param userName
     * @param password
     */
    public void login(String userName, String password) {
        Log.d(TAG, "userName:" + userName + "    password:" + password);
        EMClient.getInstance().login(userName, password, new EMCallBack() {
            @Override
            public void onSuccess() {
                EMClient.getInstance().groupManager().loadAllGroups();
                EMClient.getInstance().chatManager().loadAllConversations();
                LogUtil.d(TAG, "登陆聊天服务器成功！");
                //登录成功，更新环信用户信息:把app端的信息设置到本地的环信user
//                在调用EaseUI.getInstance().init初始化之后去设置用户信息提供者
                EaseUI easeUI = EaseUI.getInstance();
                //需要easeui库显示用户头像和昵称设置此provider
                easeUI.setUserProfileProvider(new EaseUI.EaseUserProfileProvider() {

                    @Override
                    public EaseUser getUser(String username) {
                        return getUserInfo(username);
                    }
                });
            }

            @Override
            public void onError(int i, String s) {
                LogUtil.e(TAG, "登陆聊天服务器失败！");
            }

            @Override
            public void onProgress(int i, String s) {

            }
        });
    }

    /**
     * 获取所有消息
     *
     * @param username
     * @return
     */
    public List<EMMessage> getAllMessage(String username) {
        EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username);
        if (conversation == null) {
            Log.e(TAG, "username:" + username + "  conversation is null");
            return null;
        }
        //把一条消息置为已读
        return conversation.getAllMessages();
    }

    /**
     * 获取未读消息数量
     *
     * @param username
     * @return
     */

    public int getUnreadMsgCount(String username) {
        EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username);
        return conversation.getUnreadMsgCount();
    }

    /**
     * 标记消息已读
     *
     * @param username
     */
    public void markAllMessagesAsRead(String username) {
        EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username);
        //指定会话消息未读数清零
        conversation.markAllMessagesAsRead();
    }

    /**
     * 标记一条消息已读
     *
     * @param username
     * @param messageId
     */
    public void markAllMessagesAsRead(String username, String messageId) {
        EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username);
        //把一条消息置为已读
        conversation.markMessageAsRead(messageId);
        //所有未读消息数清零
        EMClient.getInstance().chatManager().markAllConversationsAsRead();
    }

    /**
     * 获取环信EaseUser
     *
     * @param userName 环信用户名，也就是系统用户id
     * @return
     */
    private EaseUser getUserInfo(String userName) {
        EaseUser user;
        if (StringUtil.isBlank(userName)) {
            return null;
        }
        user = new EaseUser(userName);
        //环信username不是系统id
        UserModel appUserInfo = XYJApplication.getUserInfo();
        if (appUserInfo != null && userName.equals(appUserInfo.getUserId())) {//如果是自己
            user.setAvatar(appUserInfo.getHeadPic()); //头像
            user.setNick(appUserInfo.getNickName()); //昵称
        } else {
            SimpleUserDao dao = new SimpleUserDao(mContext);
            SimpleUserModel hxUser = dao.getUser(userName);
            if (hxUser != null) {
                user.setAvatar(hxUser.getHeadPic());
                user.setNick(hxUser.getNickName());
            }
        }
        return user;
    }

    protected void setEaseUIProviders() {
        //需要easeui库显示用户头像和昵称设置此provider
        easeUI.setUserProfileProvider(new EaseUI.EaseUserProfileProvider() {

            @Override
            public EaseUser getUser(String username) {
                return getUserInfo(username);
            }
        });
    }

    /**
     * 退出聊天
     */
    public void logout() {
        EMClient.getInstance().logout(true);//此方法为同步方法,里面的参数true表示退出登录时解绑GCM或者小米推送的token
        //此方法为异步方法
        EMClient.getInstance().logout(true, new EMCallBack() {

            @Override
            public void onSuccess() {
                LogUtil.d(TAG, "chat manager logout success");
            }

            @Override
            public void onProgress(int progress, String status) {

            }

            @Override
            public void onError(int code, String message) {
                LogUtil.d(TAG, "chat manager logout error, msg:" + message);
            }
        });
    }

    /**
     * 连接状态：主线程弹出相应提示
     *
     * @param event
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onConnectedEvent(HXConnectedEvent event) {
        switch (event.getErrorCode()) {
            case EMError.USER_REMOVED:// 显示帐号已经被移除
                LogUtil.d(TAG, "帐号已经被移除");
                break;
            case EMError.USER_LOGIN_ANOTHER_DEVICE:// 显示帐号在其他设备登陆
                //UI线程操作：弹出异地登录
                LogUtil.d(TAG, "帐号异地登录");
                showAnotherLoginDialog();
                break;
            default: //连接不到聊天服务器
                LogUtil.d(TAG, "连接不到聊天服务器");
                if (NetUtils.hasNetwork(mContext)) {

                } else {//当前网络不可用，请检查网络设置

                }
                break;
        }
    }

    /**
     * 显示异地登录对话框
     */
    private void showAnotherLoginDialog() {
        final Activity activity = ScreenManager.getInstance().currentActivity();
        if (activity == null) {
            return;
        }
        TipsDialog dialog = new TipsDialog(activity, "提示", "账户已在异地登录,你否重新登录？", "确定", "取消") {
            @Override
            protected void OnClickNegativeButton() {
                //取消：退出账户
                XYJApplication.getInstance().exit();
                IntentManager.getInstance().goMainActivity(activity, Intent.FLAG_ACTIVITY_CLEAR_TASK);
                this.dismiss();
            }

            @Override
            protected boolean OnClickPositiveButton() {
                //重新登录:
                XYJApplication.getInstance().exit();
                IntentManager.getInstance().goLoginActivity(mContext);
                return true;
            }
        };
        dialog.show();
    }

    /**
     * 获取消息String属性值
     *
     * @param msg
     * @param key
     * @return
     */
    private String getMsgStringAttribute(EMMessage msg, String key) {
        try {
            return msg.getStringAttribute(key);
        } catch (HyphenateException e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 批量获取用户信息
     *
     * @param ids
     */
    private void getUsersInfo(String... ids) {
        if (ids == null || ids.length == 0) {
            return;
        }
        GetUsersInfoReq req = new GetUsersInfoReq(ids);
        HttpLoader.getInstance().sendRequest(new GetUsersInfoHandler(req, new HttpResponseListener() {
            @Override
            public void onStart() {

            }

            @Override
            public void onSuccess(Object model) {
                List<UserModel> userModels = null;
                if (model != null) {
                    userModels = (List<UserModel>) model;
                }
                if (userModels != null && userModels.size() > 0) {
                    for (UserModel userModel : userModels) {
                        //保存到本地环信用户数据库
                        SimpleUserDao hxDao = new SimpleUserDao(mContext);
                        SimpleUserModel hxUser = new SimpleUserModel();
                        hxUser.setUserId(userModel.getUserId());
                        hxUser.setNickName(userModel.getNickName());
                        hxUser.setHeadPic(userModel.getHeadPic());
                        hxDao.addSimpleUser(hxUser);
                    }
                }
            }

            @Override
            public void onFail(String msg) {

            }

            @Override
            public void onDone(String msg) {

            }

            @Override
            public void onError() {

            }
        }, 0));
    }

    private static class ChatManagerHolder {
        private static final ChatManager instance = new ChatManager();
    }

    /**
     * 新消息监听器
     */
    class NewEMMessageListener implements EMMessageListener {

        @Override
        public void onMessageReceived(List<EMMessage> messages) {
            //收到消息：发送消息事件，更新小红点,保存消息的头像id昵称到数据库

            LogUtil.d(TAG, "onMessageReceived");


            if (messages != null) {
                //遍历消息获取消息详情
                for (int i = 0; i < messages.size(); i++) {
                    EMMessage msg = messages.get(i);
                    EMMessage.ChatType chatType = msg.getChatType();
                    String from = msg.getFrom();
                    String toId = msg.getTo();
                    EMMessageBody msgBody = msg.getBody();
                    long msgTime = msg.getMsgTime();
                    String msgType = getMsgStringAttribute(msg, "msgType");
                    String joinGroupId = getMsgStringAttribute(msg, "joinGroupId");
                    String groupName = getMsgStringAttribute(msg, "groupName");
                    String groupPic = getMsgStringAttribute(msg, "groupPic");
                    String partUserId = getMsgStringAttribute(msg, "partUserId");
                    String userName = getMsgStringAttribute(msg, "userName");
                    String headPic = getMsgStringAttribute(msg, "headPic");

                    LogUtil.d(TAG, String.format("receiced messsage : " +
                            "chatTpe: %s  " +
                            "from: %s  " +
                            "toId: %s  " +
                            "msgBody: %s  " +
                            "msgTime: %s  " +
                            "msgType: %s  " +
                            "joinGroupId: %s  " +
                            "groupName: %s  " +
                            "groupPic: %s  " +
                            "partUserId: %s  " +
                            "userName: %s  " +
                            "headPic: %s  " +
                            "", chatType, from, toId, msgBody.toString(), msgTime, msgType, joinGroupId, groupName, groupPic
                            , partUserId, userName, headPic));

                    //如果消息类型是加群消息推送的，则保存到数据库
                    switch (EGroupPushType.value(msgType)) {
                        case UNKNOWN: //未知消息:代表其他消息，就是单聊或者是群聊0
                            //发送新消息
                            switch (msg.getChatType()) {
                                case Chat: //发送单聊新消息:请求服务器获取用户信息
                                    EventBusUtil.postEvent(new NewMessageEvent(EMessageType.PERSON));
                                    break;
                                case GroupChat: //发送群聊新消息：请求服务器获取用户信息
                                    EventBusUtil.postEvent(new NewMessageEvent(EMessageType.GROUP));
                                    break;
                                default:
                                    break;
                            }
                            break;
                        default: //加群消息，存到数据库
                            GroupPushMsgModel msgModel = new GroupPushMsgModel();
                            msgModel.setFromId(from);
                            msgModel.setToId(toId);
                            msgModel.setMsgTime(msgTime);
                            msgModel.setMsgType(msgType);
                            msgModel.setGroupId(joinGroupId);
                            msgModel.setGroupName(groupName);
                            msgModel.setGroupPic(groupPic);
                            msgModel.setPartUserId(partUserId);
                            msgModel.setPartUserName(userName);
                            msgModel.setPartUserHead(headPic);

                            GroupPushMsgDao dao = new GroupPushMsgDao(mContext);
                            dao.add(msgModel);

                            //发送一个系统消息:先用这个当做系统消息吧
                            EventBusUtil.postEvent(new NewMessageEvent(EMessageType.SYSTEM));
                            break;
                    }
                }
            }

            //根据消息获取发送者的信息
            SimpleUserDao hxDao = new SimpleUserDao(mContext);
            List<String> idList = new ArrayList<>();
            for (int i = 0; i < messages.size(); i++) {
                String fromId = messages.get(i).getFrom();
                SimpleUserModel hxUser = hxDao.getUser(fromId);
                if (hxUser == null) {
                    idList.add(fromId);
                }
            }

            getUsersInfo((String[]) idList.toArray(new String[idList.size()]));
        }

        @Override
        public void onCmdMessageReceived(List<EMMessage> messages) {
            //收到透传消息
            LogUtil.d(TAG, "onCmdMessageReceived");
        }

        @Override
        public void onMessageReadAckReceived(List<EMMessage> messages) {
            //收到已读回执
            LogUtil.d(TAG, "onMessageReadAckReceived");
        }

        @Override
        public void onMessageDeliveryAckReceived(List<EMMessage> message) {
            //收到已送达回执
            LogUtil.d(TAG, "onMessageDeliveryAckReceived");
        }

        @Override
        public void onMessageChanged(EMMessage message, Object change) {
            //消息状态变动
            LogUtil.d(TAG, "onMessageChanged");
        }
    }

    /**
     * 监听连接状态
     */
    private class MyConnectionListener implements EMConnectionListener {
        @Override
        public void onConnected() {

        }

        @Override
        public void onDisconnected(final int error) {
            EventBusUtil.postEvent(new HXConnectedEvent(error));
        }
    }
}
